﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

// std headers
#include <memory>

// custom headers
#include "GcsService.h"
#include "CustomReplyBase.h"
#include "IResponseHandler.h"
#include "ResponseHandlerFactory.h"

namespace gmepgcs
{
    template<typename TResult>
    class CustomReply : public CustomReplyBase
    {
    public:
        explicit CustomReply(QObject *parent = nullptr);
        virtual ~CustomReply();

    public:
        void SetResponseHandler(std::shared_ptr<IResponseHandler<TResult>> pResponseHandler);
        TResult Result() const;

        void ForceFinish(const TResult &result, const std::wstring &errorMessage = std::wstring());

    protected:
        virtual void PrivateHandleReply() override;

    private:
        std::shared_ptr<IResponseHandler<TResult>> m_pResponseHandler;
        TResult m_result;
    };


    template<typename TResult>
    inline CustomReply<TResult>::CustomReply(QObject * parent) :
        CustomReplyBase(parent),
        m_pResponseHandler(nullptr),
        m_result()
    {
    }

    template<typename TResult>
    inline CustomReply<TResult>::~CustomReply()
    {
    }

    template<typename TResult>
    inline void CustomReply<TResult>::SetResponseHandler(std::shared_ptr<IResponseHandler<TResult>> pResponseHandler)
    {
        m_pResponseHandler = pResponseHandler;
    }

    template<typename TResult>
    inline TResult CustomReply<TResult>::Result() const
    {
        return m_result;
    }

    template<typename TResult>
    inline void CustomReply<TResult>::ForceFinish(const TResult & result, const std::wstring & errorMessage/* = std::wstring()*/)
    {
        m_result = result;
        m_errorMessage = errorMessage;

        emit Finished();
    }
    
    template<typename TResult>
    inline void CustomReply<TResult>::PrivateHandleReply()
    {
        try
        {
            m_result = ResponseHandlerFactory<TResult>::Handle(m_pReply, m_errorMessage);
        }
        catch (const std::exception&)
        {
            m_errorMessage = L"Unknown Error.";
            m_result = TResult();
        }
    }
}